<?php
/**
 * Created by PhpStorm.
 * User: tsingsun
 * Date: 2017/2/24
 * Time: 下午4:28
 */

namespace tsingsun\swoole\di\cm;

use Yii;
use yii\di\NotInstantiableException;

/**
 * 使用该类，替换了部分类的实现，方便YII项目的迁移
 * @package tsingsun\swoole\di
 */
class Container extends \yii\di\Container
{

    private $classCompatible = [
        'yii\web\Request' => 'tsingsun\swoole\web\Request',
        'yii\web\Response' => 'tsingsun\swoole\web\Response',
        'yii\web\ErrorHandler' => 'tsingsun\swoole\web\ErrorHandler',
        'yii\log\Logger' => 'tsingsun\swoole\log\Logger',
        'yii\web\Session' => 'tsingsun\swoole\web\cm\Session',
        'yii\web\CacheSession' => 'tsingsun\swoole\web\cm\CacheSession',
        'yii\web\DbSession' => 'tsingsun\swoole\web\cm\DbSession',
        'yii\log\FileTarget' => 'tsingsun\swoole\log\FileTarget',
        'yii\db\Command' => 'tsingsun\swoole\db\Command',
        'yii\db\Connection' => 'tsingsun\swoole\db\cm\Connection',
        'yii\redis\Connection' => 'tsingsun\swoole\redis\cm\Connection',
        'yii\redis\Session' => 'tsingsun\swoole\redis\cm\Session',
    ];

    protected $autoReplace = true;
    /**
     * 可以被持久化在内存的类
     * @var array
     */
    private $classPersistent = [
        'tsingsun\swoole\web\Request',
        'tsingsun\swoole\web\Response',
        'tsingsun\swoole\web\cm\Session',
        'tsingsun\swoole\web\cm\CacheSession',
        'tsingsun\swoole\web\cm\DbSession',
        'tsingsun\swoole\redis\cm\Session',
        'tsingsun\swoole\log\Logger',
        'tsingsun\swoole\pool\ConnectionManager',
        'tsingsun\swoole\web\ErrorHandler',
        'yii\web\UrlManager',
        'yii\i18n\I18N'
    ];

    private static $_persistents = [];

    public function setAutoReload($value)
    {
        $this->autoReplace = $value;
    }

    public function get($class, $params = [], $config = [])
    {
        return parent::get($class, $params, $config); // TODO: Change the autogenerated stub
    }


    protected function build($class, $params, $config)
    {
        if ($this->autoReplace && isset($this->classCompatible[$class])) {
            $class = $this->classCompatible[$class];
        }
        if(in_array($class, $this->classPersistent)){
            return $this->buildPersistent($class,$params,$config);
        }
        return parent::build($class, $params, $config); // TODO: Change the autogenerated stub
    }

    /**
     * 构建可持久化的类
     * @param $class
     * @param $params
     * @param $config
     * @return mixed|null|object
     * @throws NotInstantiableException
     */
    protected function buildPersistent($class, $params, $config)
    {
        $key = $this->buildKey($class,$params,$config);
        if(isset(self::$_persistents[$key])){
            return self::$_persistents[$key];
        }
        $object = parent::build($class,$params,$config);
        self::$_persistents[$key] = $object;
        return $object;
    }

    /**
     * @param $class
     * @param $params
     * @param $config
     * @return string
     */
    protected function buildKey($class, $params, $config)
    {
        return $class . md5(json_encode($params).json_encode($config));
    }

}